/***************************************************************************
 *   Copyright (C) 2008 by Thomas Richards   *
 *   thomi@colon   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "pluginmanager.h"
#include "settings.h"
#include <QFileInfo>
#include <QDebug>
#include <QDir>

#ifdef Q_OS_WIN32
#define DEFAULT_PYTHON_PATH "C:\\Python\\python.exe"
#else
#define DEFAULT_PYTHON_PATH "/usr/bin/python"
#endif

PluginManager & PluginManager::instance()
{
	static PluginManager pmObj;
	return pmObj;
}


PluginManager::PluginManager()
{
	// create plugin command line settings:
	Settings s;
	QString pythonPath = s.value("PythonPath", DEFAULT_PYTHON_PATH).toString();

	m_mapPluginCommandLines[PLUGIN_LANG_PYTHON] = pythonPath + " %1";
}


PluginManager::~PluginManager()
{
}

void PluginManager::registerPlugin(const QString & strPluginPath, tPluginType type)
{
	// need to get plugin name, before we add it to the list.
	Plugin *p = getPluginFromPath(strPluginPath);
	p->run(QStringList("--name"));
	// shouldn't take more than 10 seconds for a plugin toprint it'sname!
	if (!p->waitForFinished(10000))
	{
		qWarning() << "Plugin:" << strPluginPath << "Timed out, not registerring";
		return;
	}

	QString strPluginName = p->readAllStandardOutput().trimmed();
	if (strPluginName.isEmpty())
	{
		qWarning() << "Plugin:" << strPluginPath << "Did not report it's name, not registerring";
		return;
	}

	// got it's name, now we can register it:
	qDebug() << "Registerring plugin:" << strPluginName;
	switch(type)
	{
		case PLUGIN_TYPE_BROWSER:
		{
			qDebug("...as type BROWSER");
			m_mapBrowserPlugins[strPluginName] = strPluginPath;
		}
		break;
		case PLUGIN_TYPE_GETTER:
		{
			qDebug("...as type GETTER");
			m_mapGetterPlugins[strPluginName] = strPluginPath;
		}
		break;
		case PLUGIN_TYPE_SCANNER:
		{
			qDebug("...as type SCANNER");
			m_mapScannerPlugins[strPluginName] = strPluginPath;
		}
		break;
		case PLUGIN_TYPE_OUTPUT:
		{
			qDebug("...as type OUTPUT");
			m_mapOutputPlugins[strPluginName] = strPluginPath;
		}
		break;
	}
}

PluginManager::tPluginLanguage PluginManager::getPluginLanguage(const QString & strPluginPath) const
{
	QFileInfo fi(strPluginPath);
	Q_ASSERT_X(fi.exists(), "PluginManager::getPluginLanguage", qPrintable(strPluginPath));

	QString strExt = fi.suffix();
	if (strExt.compare("py", Qt::CaseInsensitive) == 0)
	{
		return PLUGIN_LANG_PYTHON;
	}
	else
	{
		return PLUGIN_LANG_UNKNOWN;
	}
}

Plugin * PluginManager::getPluginFromPath(const QString & strPath) const
{
	PluginManager::tPluginLanguage pluginLanguage = getPluginLanguage(strPath);
	QString strCmdLine = m_mapPluginCommandLines.value(pluginLanguage).arg(strPath);
	Plugin *pPlugin = new Plugin(strCmdLine, &instance());

	if(pluginLanguage == PluginManager::PLUGIN_LANG_PYTHON)
	{
		QStringList slEnv = QProcess::systemEnvironment();

		slEnv << QString(tr("PYTHONPATH=%1/plugins/lib").arg(QDir::currentPath()));

		pPlugin->setEnvironment(slEnv);
	}

	return pPlugin;
}

QStringList PluginManager::getAvailablePlugins(tPluginType type)
{
	switch (type)
	{
		case PLUGIN_TYPE_GETTER:
			return m_mapGetterPlugins.keys();
		case PLUGIN_TYPE_BROWSER:
			return m_mapBrowserPlugins.keys();
		case PLUGIN_TYPE_SCANNER:
			return m_mapScannerPlugins.keys();
		case PLUGIN_TYPE_OUTPUT:
			return m_mapOutputPlugins.keys();
		default:
			Q_ASSERT(false);
			return QStringList();
	}
}

Plugin * PluginManager::getPluginByName(const QString & strPluginName, tPluginType type) const
{
	QString strPluginPath;

	//qDebug() << "Looking for plugin type:" << type << "named:" << strPluginName;

	QMap<QString,QString> map;
	switch(type)
	{
		case PLUGIN_TYPE_BROWSER:
			map = m_mapBrowserPlugins;
			break;
		case PLUGIN_TYPE_GETTER:
			map = m_mapGetterPlugins;
			break;
		case PLUGIN_TYPE_SCANNER:
			map = m_mapScannerPlugins;
			break;
		case PLUGIN_TYPE_OUTPUT:
			map = m_mapOutputPlugins;
			break;
	}

	if (map.contains(strPluginName))
		strPluginPath = map.value(strPluginName);
	else
	{
		qDebug() << "Plugin:" << strPluginName << "not found:" << map;
		return NULL;
	}

	if (strPluginPath != "")
	{
		return getPluginFromPath(strPluginPath);
	}
	else return NULL;
}



